//
// Created by 67678 on 2023/3/19.
//
#include <thread>
#include <random>
#include <vector>
#include <algorithm>
#include <cassert>
#include <cstdio>
#include "fmt/format.h"
#include "../socket/socketClient.h"
#include "../socket/socketServer.h"
#include "../util/timeit.h"

using namespace std;
using namespace socket_epoll;
using namespace util;

class RandomString {
public:
    RandomString() {
        for (char ch = 'a'; ch <= 'z'; ++ch) {
            str_.push_back(ch);
            str_.push_back(ch + 'A' - 'a');
        }
    }

    string get(int n) {
        string ret;
        ret.reserve(n);
        sample(str_.begin(), str_.end(), std::back_inserter(ret), n,
               std::mt19937{std::random_device{}()});
        return ret;
    }

private:
    string str_;
};

void test(int total_connections_num, int action_per_connection) {
    cout << "webServer test begin" << endl;
    cout << "total_connections_num: " << total_connections_num << "\naction_per_connection: " << action_per_connection
         << endl;
    int threads_num = 4;
    atomic<int> cur_connections_num = 0;
    RandomString randomString;
    vector<string> strs;
    int str_len = 6;
    int nums = total_connections_num * action_per_connection;
    strs.reserve(nums);
    for (int i = 0; i < nums; ++i)
        strs.push_back(randomString.get(str_len));

    auto do_test = [&]() {
        SocketClient socketClient;
        while (true) {
            int cur = cur_connections_num++;
            if (cur >= total_connections_num) break;
            socketClient.connect(SocketServer::IP, SocketServer::PORT);
            for (int i = 0; i < action_per_connection; ++i) {
                int idx = cur * action_per_connection + i;
                socketClient.write(fmt::format("set {0} {0} \r\n", strs[idx]));
                string r = socketClient.read();
                if (r.empty())
                    cout << 1 << endl;
                if (!r.starts_with("OK"))
                    cout << fmt::format("set failed {}", strs[idx]) << endl;
                socketClient.write(fmt::format("get {0} \r\n", strs[idx]));
                string ret = socketClient.read();
                if (!ret.starts_with(strs[idx]))
                    cout << fmt::format("get wrong answer {}->{}", ret, strs[idx]) << endl;
            }
            socketClient.close();
        }
    };
    vector<thread> vec;
    for (int i = 0; i < threads_num; ++i) {
        vec.emplace_back([=]() { time_it(do_test); });
    }
    for (int i = 0; i < threads_num; ++i) {
        vec[i].join();
    }

    cout << "webServer test end" <<
         endl;

}

int main() {
    test(100, 10);
    test(100, 100);
    test(100, 1000);
    test(1000, 10);
    test(1000, 100);
    test(1000, 1000);
    test(10000, 10);
    test(10000, 100);
    test(10000, 1000);
}